home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / srcuc.zip / UXIO.C < prev    next >
C/C++ Source or Header  |  1992-03-26  |  11KB  |  445 lines

  1. /* -*-C-*-
  2.  
  3. $Header: /scheme/src/microcode/RCS/uxio.c,v 1.21 1992/03/26 11:02:42 cph Exp $
  4.  
  5. Copyright (c) 1990-1992 Massachusetts Institute of Technology
  6.  
  7. This material was developed by the Scheme project at the Massachusetts
  8. Institute of Technology, Department of Electrical Engineering and
  9. Computer Science.  Permission to copy this software, to redistribute
  10. it, and to use it for any purpose is granted, subject to the following
  11. restrictions and understandings.
  12.  
  13. 1. Any copy made of this software must include this copyright notice
  14. in full.
  15.  
  16. 2. Users of this software agree to make their best efforts (a) to
  17. return to the MIT Scheme project any improvements or extensions that
  18. they make, so that these may be included in future releases; and (b)
  19. to inform MIT of noteworthy uses of this software.
  20.  
  21. 3. All materials developed as a consequence of the use of this
  22. software shall duly acknowledge such use, in accordance with the usual
  23. standards of acknowledging credit in academic research.
  24.  
  25. 4. MIT has made no warrantee or representation that the operation of
  26. this software will be error-free, and MIT is under no obligation to
  27. provide any services, by way of maintenance, update, or otherwise.
  28.  
  29. 5. In conjunction with products arising from the use of this material,
  30. there shall be no use of the name of the Massachusetts Institute of
  31. Technology nor of any adaptation thereof in any advertising,
  32. promotional, or sales literature without prior written consent from
  33. MIT in each case. */
  34.  
  35. #include "ux.h"
  36. #include "uxio.h"
  37. #include "uxselect.h"
  38.  
  39. size_t OS_channel_table_size;
  40. struct channel * channel_table;
  41.  
  42. #ifdef FD_SET
  43. #define SELECT_TYPE fd_set
  44. #else
  45. #define SELECT_TYPE int
  46. #define FD_SETSIZE ((sizeof (int)) * CHAR_BIT)
  47. #define FD_SET(n, p) ((*(p)) |= (1 << (n)))
  48. #define FD_CLR(n, p) ((*(p)) &= ~(1 << (n)))
  49. #define FD_ISSET(n, p) (((*(p)) & (1 << (n))) != 0)
  50. #define FD_ZERO(p) ((*(p)) = 0)
  51. #endif
  52.  
  53. unsigned int OS_channels_registered;
  54. static SELECT_TYPE input_descriptors;
  55. #ifdef HAVE_SELECT
  56. static struct timeval zero_timeout;
  57. #endif
  58.  
  59. static void
  60. DEFUN_VOID (UX_channel_close_all)
  61. {
  62.   Tchannel channel;
  63.   for (channel = 0; (channel < OS_channel_table_size); channel += 1)
  64.     if (CHANNEL_OPEN_P (channel))
  65.       OS_channel_close_noerror (channel);
  66. }
  67.  
  68. extern void EXFUN (add_reload_cleanup, (void (*) (void)));
  69.  
  70. void
  71. DEFUN_VOID (UX_initialize_channels)
  72. {
  73.   OS_channel_table_size = (UX_SC_OPEN_MAX ());
  74.   channel_table =
  75.     (UX_malloc (OS_channel_table_size * (sizeof (struct channel))));
  76.   if (channel_table == 0)
  77.     {
  78.       fprintf (stderr, "\nUnable to allocate channel table.\n");
  79.       fflush (stderr);
  80.       termination_init_error ();
  81.     }
  82.   {
  83.     Tchannel channel;
  84.     for (channel = 0; (channel < OS_channel_table_size); channel += 1)
  85.       MARK_CHANNEL_CLOSED (channel);
  86.   }
  87.   add_reload_cleanup (UX_channel_close_all);
  88.   FD_ZERO (&input_descriptors);
  89.   OS_channels_registered = 0;
  90. #ifdef HAVE_SELECT
  91.   (zero_timeout . tv_sec) = 0;
  92.   (zero_timeout . tv_usec) = 0;
  93. #endif
  94. }
  95.  
  96. void
  97. DEFUN_VOID (UX_reset_channels)
  98. {
  99.   UX_free (channel_table);
  100.   channel_table = 0;
  101.   OS_channel_table_size = 0;
  102. }
  103.  
  104. Tchannel
  105. DEFUN_VOID (channel_allocate)
  106. {
  107.   Tchannel channel = 0;
  108.   while (1)
  109.     {
  110.       if (channel == OS_channel_table_size)
  111.     error_out_of_channels ();
  112.       if (CHANNEL_CLOSED_P (channel))
  113.     return (channel);
  114.       channel += 1;
  115.     }
  116. }
  117.  
  118. int
  119. DEFUN (OS_channel_open_p, (channel), Tchannel channel)
  120. {
  121.   return (CHANNEL_OPEN_P (channel));
  122. }
  123.  
  124. void
  125. DEFUN (OS_channel_close, (channel), Tchannel channel)
  126. {
  127.   if (! (CHANNEL_INTERNAL (channel)))
  128.     {
  129.       if (CHANNEL_REGISTERED (channel))
  130.     OS_channel_unregister (channel);
  131.       STD_VOID_SYSTEM_CALL
  132.     (syscall_close, (UX_close (CHANNEL_DESCRIPTOR (channel))));
  133.       MARK_CHANNEL_CLOSED (channel);
  134.     }
  135. }
  136.  
  137. void
  138. DEFUN (OS_channel_close_noerror, (channel), Tchannel channel)
  139. {
  140.   if (! (CHANNEL_INTERNAL (channel)))
  141.     {
  142.       if (CHANNEL_REGISTERED (channel))
  143.     OS_channel_unregister (channel);
  144.       UX_close (CHANNEL_DESCRIPTOR (channel));
  145.       MARK_CHANNEL_CLOSED (channel);
  146.     }
  147. }
  148.  
  149. static void
  150. DEFUN (channel_close_on_abort_1, (cp), PTR cp)
  151. {
  152.   OS_channel_close (* ((Tchannel *) cp));
  153. }
  154.  
  155. void
  156. DEFUN (OS_channel_close_on_abort, (channel), Tchannel channel)
  157. {
  158.   Tchannel * cp = (dstack_alloc (sizeof (Tchannel)));
  159.   (*cp) = (channel);
  160.   transaction_record_action (tat_abort, channel_close_on_abort_1, cp);
  161. }
  162.  
  163. enum channel_type
  164. DEFUN (OS_channel_type, (channel), Tchannel channel)
  165. {
  166.   return (CHANNEL_TYPE (channel));
  167. }
  168.  
  169. long
  170. DEFUN (OS_channel_read, (channel, buffer, nbytes),
  171.        Tchannel channel AND
  172.        PTR buffer AND
  173.        size_t nbytes)
  174. {
  175.   if (nbytes == 0)
  176.     return (0);
  177.   while (1)
  178.     {
  179.       long scr = (UX_read ((CHANNEL_DESCRIPTOR (channel)), buffer, nbytes));
  180.       if (scr < 0)
  181.     {
  182. #ifdef ERRNO_NONBLOCK
  183.       if (errno == ERRNO_NONBLOCK)
  184.         return (-1);
  185. #endif
  186.       UX_prim_check_errno (syscall_read);
  187.       continue;
  188.     }
  189.       if (scr > nbytes)
  190.     error_external_return ();
  191. #ifdef AMBIGUOUS_NONBLOCK
  192.       return ((scr > 0) ? scr : (CHANNEL_NONBLOCKING (channel)) ? (-1) : 0);
  193. #else
  194.       return (scr);
  195. #endif
  196.     }
  197. }
  198.  
  199. long
  200. DEFUN (OS_channel_write, (channel, buffer, nbytes),
  201.        Tchannel channel AND
  202.        CONST PTR buffer AND
  203.        size_t nbytes)
  204. {
  205.   if (nbytes == 0)
  206.     return (0);
  207.   while (1)
  208.     {
  209.       long scr = (UX_write ((CHANNEL_DESCRIPTOR (channel)), buffer, nbytes));
  210.       if (scr < 0)
  211.     {
  212. #ifdef ERRNO_NONBLOCK
  213.       if (errno == ERRNO_NONBLOCK)
  214.         return (-1);
  215. #endif
  216.       UX_prim_check_errno (syscall_write);
  217.       continue;
  218.     }
  219.       if (scr > nbytes)
  220.     error_external_return ();
  221.       return ((scr > 0) ? scr : (-1));
  222.     }
  223. }
  224.  
  225. size_t
  226. DEFUN (OS_channel_read_load_file, (channel, buffer, nbytes),
  227.        Tchannel channel AND PTR buffer AND size_t nbytes)
  228. {
  229.   int scr = (UX_read ((CHANNEL_DESCRIPTOR (channel)), buffer, nbytes));
  230.   return ((scr < 0) ? 0 : scr);
  231. }
  232.  
  233. size_t
  234. DEFUN (OS_channel_write_dump_file, (channel, buffer, nbytes),
  235.        Tchannel channel AND CONST PTR buffer AND size_t nbytes)
  236. {
  237.   int scr = (UX_write ((CHANNEL_DESCRIPTOR (channel)), buffer, nbytes));
  238.   return ((scr < 0) ? 0 : scr);
  239. }
  240.  
  241. extern int EXFUN (strlen, (CONST char *));
  242.  
  243. void
  244. DEFUN (OS_channel_write_string, (channel, string),
  245.        Tchannel channel AND
  246.        CONST char * string)
  247. {
  248.   unsigned long length = (strlen (string));
  249.   if ((OS_channel_write (channel, string, length)) != length)
  250.     error_external_return ();
  251. }
  252.  
  253. void
  254. DEFUN (OS_make_pipe, (readerp, writerp),
  255.        Tchannel * readerp AND
  256.        Tchannel * writerp)
  257. {
  258.   int pv [2];
  259.   transaction_begin ();
  260.   STD_VOID_SYSTEM_CALL (syscall_pipe, (UX_pipe (pv)));
  261.   MAKE_CHANNEL ((pv[0]), channel_type_pipe, (*readerp) =);
  262.   OS_channel_close_on_abort (*readerp);
  263.   MAKE_CHANNEL ((pv[1]), channel_type_pipe, (*writerp) =);
  264.   transaction_commit ();
  265. }
  266.  
  267. #ifdef FCNTL_NONBLOCK
  268.  
  269. static int
  270. DEFUN (get_flags, (fd), int fd)
  271. {
  272.   int scr;
  273.   STD_UINT_SYSTEM_CALL (syscall_fcntl_GETFL, scr, (UX_fcntl (fd, F_GETFL, 0)));
  274.   return (scr);
  275. }
  276.  
  277. static void
  278. DEFUN (set_flags, (fd, flags), int fd AND int flags)
  279. {
  280.   STD_VOID_SYSTEM_CALL (syscall_fcntl_SETFL, (UX_fcntl (fd, F_SETFL, flags)));
  281. }
  282.  
  283. int
  284. DEFUN (OS_channel_nonblocking_p, (channel), Tchannel channel)
  285. {
  286.   return (CHANNEL_NONBLOCKING (channel));
  287. }
  288.  
  289. void
  290. DEFUN (OS_channel_nonblocking, (channel), Tchannel channel)
  291. {
  292.   int fd = (CHANNEL_DESCRIPTOR (channel));
  293.   int flags = (get_flags (fd));
  294.   if ((flags & FCNTL_NONBLOCK) == 0)
  295.     set_flags (fd, (flags | FCNTL_NONBLOCK));
  296.   (CHANNEL_NONBLOCKING (channel)) = 1;
  297. }
  298.  
  299. void
  300. DEFUN (OS_channel_blocking, (channel), Tchannel channel)
  301. {
  302.   int fd = (CHANNEL_DESCRIPTOR (channel));
  303.   int flags = (get_flags (fd));
  304.   if ((flags & FCNTL_NONBLOCK) != 0)
  305.     set_flags (fd, (flags &~ FCNTL_NONBLOCK));
  306.   (CHANNEL_NONBLOCKING (channel)) = 0;
  307. }
  308.  
  309. #else /* not FCNTL_NONBLOCK */
  310.  
  311. int
  312. DEFUN (OS_channel_nonblocking_p, (channel), Tchannel channel)
  313. {
  314.   return (-1);
  315. }
  316.  
  317. void
  318. DEFUN (OS_channel_nonblocking, (channel), Tchannel channel)
  319. {
  320.   error_unimplemented_primitive ();
  321. }
  322.  
  323. void
  324. DEFUN (OS_channel_blocking, (channel), Tchannel channel)
  325. {
  326. }
  327.  
  328. #endif /* FCNTL_NONBLOCK */
  329.  
  330. int
  331. DEFUN (OS_channel_registered_p, (channel), Tchannel channel)
  332. {
  333.   return (CHANNEL_REGISTERED (channel));
  334. }
  335.  
  336. void
  337. DEFUN (OS_channel_register, (channel), Tchannel channel)
  338. {
  339. #ifdef HAVE_SELECT
  340.   if (! (CHANNEL_REGISTERED (channel)))
  341.     {
  342.       FD_SET ((CHANNEL_DESCRIPTOR (channel)), (&input_descriptors));
  343.       OS_channels_registered += 1;
  344.       (CHANNEL_REGISTERED (channel)) = 1;
  345.     }
  346. #else
  347.   error_unimplemented_primitive ();
  348. #endif
  349. }
  350.  
  351. void
  352. DEFUN (OS_channel_unregister, (channel), Tchannel channel)
  353. {
  354.   if (CHANNEL_REGISTERED (channel))
  355.     {
  356.       FD_CLR ((CHANNEL_DESCRIPTOR (channel)), (&input_descriptors));
  357.       OS_channels_registered -= 1;
  358.       (CHANNEL_REGISTERED (channel)) = 0;
  359.     }
  360. }
  361.  
  362. #if defined(_HPUX) && (_HPUX_VERSION >= 80)
  363. #define SELECT_DECLARED
  364. #endif
  365.  
  366. #ifdef HAVE_SELECT
  367. CONST int UX_have_select_p = 1;
  368. extern int EXFUN (UX_process_any_status_change, (void));
  369. #ifndef SELECT_DECLARED
  370. extern int EXFUN (UX_select,
  371.           (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
  372.            struct timeval *));
  373. #endif /* not SELECT_DECLARED */
  374. #else /* not HAVE_SELECT */
  375. CONST int UX_have_select_p = 0;
  376. #endif /* not HAVE_SELECT */
  377.  
  378. enum select_input
  379. DEFUN (UX_select_input, (fd, blockp), int fd AND int blockp)
  380. {
  381. #ifdef HAVE_SELECT
  382.   int status_change_p;
  383.   int nfds;
  384.   SELECT_TYPE readable;
  385.  
  386.   readable = input_descriptors;
  387.   FD_SET (fd, (&readable));
  388.   while (1)
  389.     {
  390.       status_change_p = 0;
  391.       INTERRUPTABLE_EXTENT
  392.     (nfds,
  393.      ((status_change_p = (UX_process_any_status_change ()))
  394.       ? ((errno = EINTR), (-1))
  395.       : (UX_select (FD_SETSIZE,
  396.             (&readable),
  397.             ((SELECT_TYPE *) 0),
  398.             ((SELECT_TYPE *) 0),
  399.             (blockp
  400.              ? ((struct timeval *) 0)
  401.              : (&zero_timeout))))));
  402.       if (nfds > 0)
  403.     return
  404.       ((FD_ISSET (fd, (&readable)))
  405.        ? select_input_argument
  406.        : select_input_other);
  407.       else if (nfds == 0)
  408.     {
  409.       if (!blockp)
  410.         return (select_input_none);
  411.     }
  412.       else if (errno != EINTR)
  413.     error_system_call (errno, syscall_select);
  414.       else if (status_change_p)
  415.     return (select_input_process_status);
  416.       if (pending_interrupts_p ())
  417.     return (select_input_interrupt);
  418.     }
  419. #else
  420.   error_system_call (ENOSYS, syscall_select);
  421.   return (select_input_argument);
  422. #endif
  423. }
  424.  
  425. long
  426. DEFUN (OS_channel_select_then_read, (channel, buffer, nbytes),
  427.        Tchannel channel AND
  428.        PTR buffer AND
  429.        size_t nbytes)
  430. {
  431.   switch (UX_select_input ((CHANNEL_DESCRIPTOR (channel)),
  432.                (! (CHANNEL_NONBLOCKING (channel)))))
  433.     {
  434.     case select_input_none:
  435.       return (-1);
  436.     case select_input_other:
  437.       return (-2);
  438.     case select_input_process_status:
  439.       return (-3);
  440.     case select_input_interrupt:
  441.       return (-4);
  442.     }
  443.   return (OS_channel_read (channel, buffer, nbytes));
  444. }
  445.